package com.lwq.imserver.service;

import com.auth0.jwt.interfaces.Claim;
import com.lwq.imserver.model.SendBody;
import com.lwq.imserver.model.TransferModel;
import com.lwq.imserver.model.system.SysUser;
import com.lwq.imserver.model.system.TokenModel;
import com.lwq.imserver.util.Base64Util;
import com.lwq.imserver.util.RedisUtil;
import com.lwq.imserver.util.TokenUtil;
import com.lwq.imserver.util.WebSocketUtil;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Description:
 * Author: LiuWenQing
 * Datetime: 2022/1/20 15:30
 */
@Service
public class LoginService {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private RedisUtil redis;
    @Autowired
    private PasswordEncoder pe;
    @Value("${token.expire}")
    private Integer tokenExpire;

    @Transactional(rollbackFor = Exception.class)
    public TokenModel doLogin(SysUser user) {
        List<SysUser> models = mongoTemplate.find(new Query().addCriteria(new Criteria().and("name").is(user.getName())), SysUser.class);
        if (models.isEmpty()) throw new RuntimeException("账号不存在");
        if (!pe.matches(user.getPassword(), models.get(0).getPassword())) throw new RuntimeException("账号或密码错误");
        TokenModel tk = null;
        try {
            if (!StringUtils.isEmpty(redis.get(models.get(0).getId().toString())))
                redis.del(models.get(0).getId().toString());
            tk = this.createToken(models.get(0));
        } catch (Exception e) {
            throw new RuntimeException("创建token异常");
        }
        redis.put(models.get(0).getId().toString(), tk.getAccess(), tokenExpire, TimeUnit.HOURS);
        models.get(0).setLastLoginDate(new Date());
        mongoTemplate.updateFirst(new Query()
                        .addCriteria(new Criteria().and("name").is(user.getName()))
                , new Update().update("lastLoginDate" , new Date()), SysUser.class);
        WebSocketUtil.broadCast(new SendBody("", TransferModel.LOGIN,models.get(0).getUserName()));
        return tk;
    }

    public void logout(String token) {
        if (StringUtils.isNotEmpty(token)) {
            Map<String, Claim> map = null;
            try {
                map = TokenUtil.verifyToken(token);
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }
            if (redis.get(map.get("userId").asString()) != null){
                redis.del(map.get("userId").asString());
            }
        }
    }

    private TokenModel createToken(SysUser user) throws Exception {
        TokenModel tk = new TokenModel();
        tk.setAccess(TokenUtil.createToken(user, tokenExpire));
        tk.setId(user.getId());
        tk.setName(user.getName());
        tk.setUserName(user.getUserName());
        tk.setAge(user.getAge());
        tk.setSex(user.getSex());
        tk.setAvatar(user.getAvatar());
        return tk;
    }

    private TokenModel createToken(SysUser user, String token) {
        TokenModel tk = new TokenModel();
        tk.setAccess(token);
        tk.setId(user.getId());
        tk.setName(user.getName());
        tk.setUserName(user.getUserName());
        tk.setAge(user.getAge());
        tk.setSex(user.getSex());
        tk.setAvatar(user.getAvatar());
        return tk;
    }


}
